import base64
from typing import Literal, Dict, Any, Optional, Union

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field
from pydantic_core import ValidationError
from dao.es_dao.card_dao import find_imei
from dao.mongo_dao.l16_log_dao import query_health_data
from model.wristband_models import LocationData, HealthData, BatteryData, WarningData, AudioData
from service.audio import handle_audio
from service.battery import handle_step
from service.l16_handler import handle_health, handle_warning
from service.location import location_handle_new
from utils.aliyun_token_util import tts, get_token, mp3_to_amr_b64, string_to_b64_via_tmp
from utils.command_util import send_set_device_config
from utils.logger_util import logger, save_data_log_mongo

l16_router = APIRouter(prefix="/test/wristband", tags=['手环L16'])


@l16_router.post("/api")
async def unified_api_entry(raw_data: Dict[str, Any]):
    try:
        # 关键参数检查
        if "action" not in raw_data:
            raise HTTPException(400, "缺少 action 参数")

        action = raw_data["action"]
        logger.info(f" 收到 {action} 类型请求")
        # 保存原始日志
        await save_data_log_mongo(raw_data)
        # 动态路由和模型验证
        validated_data: BaseModel = await dynamic_model_router(action, raw_data)
        # 执行对应处理器
        handler = HANDLER_MAPPER.get(action)
        if not handler:
            raise ValueError(f"未注册的 action 处理器: {action}")

        await handler(validated_data)
        return {"status": 1, "message": "处理成功"}

    except Exception as e:
        logger.exception(" 系统处理异常")
        raise HTTPException(500, "服务器内部错误")


async def dynamic_model_router(action: str, raw_data: Dict[str, Any]) -> BaseModel:
    """动态选择并验证数据模型"""
    model_class = MODEL_ROUTER.get(action)
    if not model_class:
        raise ValueError(f"未知的 action 类型: {action}")

    try:
        # Pydantic 自动验证并转换数据类型
        return model_class(**raw_data)
    except ValidationError as e:
        logger.error(f" 数据验证失败: {str(e)}")
        raise HTTPException(status_code=422, detail=e.errors())


@l16_router.post("/command")
async def command(data: dict) -> dict:
    result = send_set_device_config(data)
    return result


@l16_router.post("/command_sendMessage")
async def command(data: dict) -> dict:
    """
    总入口：把文字转换→AMR(Base64)并发送
    """
    # aliyun_token = await get_aliyun_token()
    # b64_amr = text_to_amr_b64(data['body']['content'])
    if data['body']['type'] == 0:
        audio_bytes = tts(data['body']['content'], get_token(), data['body'].get('voice'))
        audio_b64 = mp3_to_amr_b64(audio_bytes)
        data['body']['content'] = audio_b64
    # else:
    #     encoded_str = string_to_b64_via_tmp(data['body']['content'])
    #     data['body']['content'] = encoded_str
    result = send_set_device_config(data)
    return {'success': True, 'result': result}


@l16_router.post("/batch_command")
async def batch_command(data: dict) -> dict:
    imei_list = data.get('imei_list')
    if imei_list is None:
        if data.get('projectId') is not None:
            imei_list = await find_imei(data)
        else:
            return {"status": 0, "result": "设置失败", "message": "缺少参数,projectId或imei_list"}
    common_data = data
    result_list = []
    for imei in imei_list:
        common_data['body']['imei'] = imei
        result_list.append(send_set_device_config(common_data))
        print(common_data)
    return {"status": 1, "result": result_list}


class ApiRequest(BaseModel):
    device_id: str = Field(..., min_length=6)
    action: Literal["location", "health", "battery", "warning", "audio"]
    timestamp: int
    battery: Optional[int] = Field(None, ge=0, le=100)
    pedometer: Optional[int] = Field(None, ge=0)
    coordinates: Optional[Dict[str, float]] = None
    health_metrics: Optional[Dict[str, Any]] = None
    alert_type: Optional[str] = None


class UnifiedResponse(BaseModel):
    request_id: str
    status: Literal[0, 1]
    message: str
    timestamp: float


MODEL_ROUTER = {
    "location": LocationData,
    "health": HealthData,
    "battery": BatteryData,
    "warning": WarningData,
    "audio": AudioData
}

# 核心处理器映射表
HANDLER_MAPPER = {
    "location": location_handle_new,
    "health": handle_health,
    "battery": handle_step,
    "warning": handle_warning,
    "audio": handle_audio
}

RequestType = Union[LocationData, HealthData, BatteryData, WarningData, AudioData]
